package com.merry.beanFactory.bf;

import java.beans.PropertyEditor;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.PropertyEditorRegistrySupport;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanIsAbstractException;
import org.springframework.beans.factory.BeanIsNotAFactoryException;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.CannotLoadBeanClassException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.Scope;
import org.springframework.beans.factory.support.*;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.DecoratingClassLoader;
import org.springframework.core.NamedThreadLocal;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.log.LogMessage;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.StringValueResolver;

/**
 * 一个重要的抽象类，实现了 {@link BeanFactory} 接口，完成了 {@link ConfigurableBeanFactory} 的全部功能。
 *  这个类提供了一个单例缓存 通过类 {@link DefaultSingletonBeanRegistry} ， 也继承了 {@link HierarchicalBeanFactory} 功能。
 *
 *  注意：这个类的模板方法将有子类实现模板方法为 {@link #getBeanDefinition} 、{@link #createBean}
 *  分别是获取bean的定义和创建bean， 默认的子类实现可以在  {@link DefaultListableBeanFactory} 和 {@link AbstractAutowireCapableBeanFactory} 中找到。
 */
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    /** 父容器变量，这是为了解决容器分层的问题 */
    @Nullable
    private BeanFactory parentBeanFactory;

    /** bean的类加载器的默认实现 */
    @Nullable
    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    /** 必要时，使用ClassLoader临时解析bean类名。 */
    @Nullable
    private ClassLoader tempClassLoader;

    /** 是缓存bean元数据，还是每次都重新获取它。 */
    private boolean cacheBeanMetadata = true;

    /** beanDefinitionValue 中的表达式的解析策略。 */
    @Nullable
    private BeanExpressionResolver beanExpressionResolver;

    /** Spring 使用的服务转换器来代替 PropertyEditors. */
    @Nullable
    private ConversionService conversionService;

    /** 后续使用服务转换器来代替了 */
    private final Set<PropertyEditorRegistrar> propertyEditorRegistrars = new LinkedHashSet<>(4);

    /** 后续已经使用服务转换器来代替了 */
    private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap<>(4);

    /** 要使用的自定义TypeConverter，覆盖默认的PropertyEditor机制。 */
    @Nullable
    private TypeConverter typeConverter;

    /** String类型的解析器。 */
    private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>();

    /** BeanPostProcessors的列表。 */
    private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

    /** 指示是否已注册任何 InstantiationAwareBeanPostProcessors。 这个接口 【InstantiationAwareBeanPostProcessor】 是一个很重要的接口，它与AOP的创建有关。 */
    private volatile boolean hasInstantiationAwareBeanPostProcessors;

    /** 指示是否已注册任何 DestructionAwareBeanPostProcessors。这个接口 【DestructionAwareBeanPostProcessor】 是当bean在销毁的时候，允许执行自定义的逻辑。 */
    private volatile boolean hasDestructionAwareBeanPostProcessors;

    /** 从作用域标识符字符串映射到相应的作用域。在单例/原型链中没用，但是在 web 容器中，比如 request/session 就需要这个字段。 */
    private final Map<String, Scope> scopes = new LinkedHashMap<>(8);

    /** 与 SecurityManager一起运行时使用的安全上下文。 */
    @Nullable
    private SecurityContextProvider securityContextProvider;

    /** 集合：专门存储 beanName 和 merged RootBeanDefinition。 RootBeanDefinition 对象就是没有父子关系的对象，在创建bean对象是使用。 */
    private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);

    /** 已经创建过至少一次的beanName，以免重复创建单例bean。  */
    private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));

    /** 当前正在创建的原型链的 bean的名称。 */
    private final ThreadLocal<Object> prototypesCurrentlyInCreation =
            new NamedThreadLocal<>("Prototype beans currently in creation");


    /**
     * 构造器
     */
    public AbstractBeanFactory() {
    }

    /**
     * 构造器，指定一个父容器，这个在容器的分层结构中被使用。
     */
    public AbstractBeanFactory(@Nullable BeanFactory parentBeanFactory) {
        this.parentBeanFactory = parentBeanFactory;
    }


    //---------------------------------------------------------------------
    // 实现 BeanFactory 接口的方法。
    //---------------------------------------------------------------------

    /**
     * 获取bean，最后都会调用 {@link #doGetBean} 方法来完成。
     */
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        return doGetBean(name, requiredType, null, false);
    }

    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        return doGetBean(name, null, args, false);
    }

    public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
            throws BeansException {
        return doGetBean(name, requiredType, args, false);
    }

    /**
     * 获取bean实际上干活的方法。 doGetBean。
     */
    @SuppressWarnings("unchecked")
    protected <T> T doGetBean(
            String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
            throws BeansException {
        //1：获取到真正beanName，主要是为了适配别名，比如：如果我传入了一个别名，那么通过这个方法，获取到的就是真正的beanName了。
        String beanName = transformedBeanName(name);
        Object bean;

        //2：首先先检查单例缓存中是否有手动注册的单例。 这个方法会跳到 【DefaultSingletonBeanRegistry#getSingleton】 方法中解决，这个方法也就是处理三级缓存的问题的代码。
        Object sharedInstance = getSingleton(beanName);
        //3.1：如果在缓存中获取到了单例bean。
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            //3.1.1：返回真正的bean，这是为了解决工厂bean，会返回当前工厂bean，而不是bean的方法。
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        //3.2：如果没有获取到单例bean，这是表示当前bean是一个原型链的bean，或者是一个单例bean但是没有创建。
        else {
            //如果当前线程正在创建这个原型链bean，那就意味者当前bean出现了循环依赖，容器无法解决原型链bean的循环依赖，所以直接出现异常。
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 先检查一个当前容器，是否存在父容器，这个是 【HierarchicalBeanFactory】 接口中的内容哦。
            BeanFactory parentBeanFactory = getParentBeanFactory();
            //如果父容器不为空，并且 【当前？】 容器不包含当前bean，那么就要找父容器来解决了。这个方法是模板方法，如果我们想要支持分层接口，那么就需要在本层中查找。
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                //先获取到原来的beanName，主要还是针对 工厂bean，如果是工厂 bean，我需要将 & 加上。
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    //如果父容器是 【AbstractBeanFactory】，那么就调用 doGetBean 方法继续获取。
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // 调用父级的方法获取bean。
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    // 调用父级的方法获取bean。
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    // 调用父级的方法获取bean。
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }

            if (!typeCheckOnly) {
                //标记当前bean已经被创建。
                markBeanAsCreated(beanName);
            }
            // 方法如果到了这一步，那么就到了该方法去生成bean了。
            try {
                //根据beanName获取一个 RootBeanDefinition 对象，这个对象是没有父子结构的 BeanDefinition 对象，容器中就是通过这个 BeanDefinition 对象完成bean的创建的。
                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                //检查一下是不是一个抽象类，抽象类就直接出异常。
                checkMergedBeanDefinition(mbd, beanName, args);

                // 先执行当前bean的 depends on依赖。
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        // 判断是不是在 depends on 代码中出现了循环依赖，容器不能解决 这种情况的循环依赖。
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        //先创建一个依赖的关系，表示当前bean依赖与某个bean。这样在注销当前bean的时候，可以将依赖的bean一起注销掉。
                        registerDependentBean(dep, beanName);
                        try {
                            //getBean方法获取依赖的bean。
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                //开始创建bean的实例。
                if (mbd.isSingleton()) {
                    //调用专门创建单例的类完成单例bean的创建： {@link DefaultSingletonBeanRegistry#getSingleton}
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            //具体的创建流程由子类实现。
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    //如果这个bean是一个工厂bean，那么调用 FactoryBean#getObject 方法返回真正的方法。
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                //开始创建原型链的bean。
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        //标记一下，当前bean正在被创建。
                        beforePrototypeCreation(beanName);
                        //创建bean。
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        //当前bean创建完了，需要清除一些信息。
                        afterPrototypeCreation(beanName);
                    }
                    //处理工厂bean。
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
                //如果当前bean既不是一个单例bean，也不是一个原型链的bean，则调用 Scope 获取它的作用域。
                else {
                    String scopeName = mbd.getScope();
                    if (!StringUtils.hasLength(scopeName)) {
                        throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
                    }
                    Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        //创建bean，并放入作用域中。
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                //创建bean的实际方法。
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        //处理工厂bean。
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                        "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        //现在bean的创建已经完成了。下面进行类型转换， 【TypeConverter】。由于之前创建的bean 是 【Object】 类的，所以需要对这个bean进行类型转换，转成 User、Dog等我们想要的类。
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }
    //doGetBean 方法完成，实际上就干了几件事，1.尝试从缓存中获取bean，如果没有。2.看看当前类是否由这个BeanDefinition，如果没有，则调用父容器的方法获取bean。
    //      3.开始从当前容器创建bean。包括，先创建depends on依赖的bean，之后在调用 createBean方法创建bean。


    /**
     * 判断当前容器或者父容器中是否有这个beanName。
     */
    @Override
    public boolean containsBean(String name) {
        String beanName = transformedBeanName(name);
        if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
            return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
        }
        // Not found -> check parent.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
    }

    /**
     * 判断当前bean是不是一个单例bean。
     * 逻辑流程大约为：首先判断当前bean是不是一个单例bean，如果是，那么就有两种可能：1.当前bean是一个工厂bean，那么就需要判断当前工厂bean返回的对象是不是一个单例bean。
     *      2.如果当前bean不是一个工厂bean，那么就直接返回这是一个单例bean。
     */
    @Override
    public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        //获取真正的BeanName，主要是解决工厂Bean有前缀 & 的问题。
        String beanName = transformedBeanName(name);

        //调用专门获取单例bean的方法获取单例bean，这个入参表示它无法处理循环依赖。注意这个方法只能获取，或者从三级缓存中创建bean，他无法像 createBean 方法一样创建bean。
        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null) {
            if (beanInstance instanceof FactoryBean) {
                return (BeanFactoryUtils.isFactoryDereference(name) || ((FactoryBean<?>) beanInstance).isSingleton());
            }
            else {
                return !BeanFactoryUtils.isFactoryDereference(name);
            }
        }

        //如果当前容器没有这个bean，并且它还有父容器。
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 交给父容器判断了。
            return parentBeanFactory.isSingleton(originalBeanName(name));
        }
        //获取一个没有父子结构的BeanDefinition。
        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

        //判断是不是一个单例的方法，主要有，判断当前mbd是不是一个单例，如果是，则判断它是不是一个工厂bean，如果是，就调用工厂bean的判断是不是一个单例的方法来返回是不是一个单例。
        if (mbd.isSingleton()) {
            if (isFactoryBean(beanName, mbd)) {
                if (BeanFactoryUtils.isFactoryDereference(name)) {
                    return true;
                }
                FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                return factoryBean.isSingleton();
            }
            else {
                return !BeanFactoryUtils.isFactoryDereference(name);
            }
        }
        else {
            return false;
        }
    }

    /**
     * 判断一个bean是不是一个原型链的bean。大致逻辑如下：
     *  1.判断当前bean是一个原型链的bean：那么需要判断下它是不是一个工厂bean，工厂bean由额外的逻辑。
     *
     *  2.如果当前bean不是一个原型链bean：那么它还需要判断是不是一个 工厂bean，这个 工厂bean 返回的bean是不是一个原型链bean。
     *
     *  总之：无论是判断当前bean是不是一个单例bean，还是原型链bean，都需要考虑一种情况：
     *      1.如果这个bean是一个普通的bean，那么它的作用域由 BeanDefinition 对象控制。
     *      2.如果这个bean是一个 工厂bean。FactoryBean，那么它的作用域将由 BeanDefinition 和 {FactoryBean#isSingleton}方法共同控制。
     */
    @Override
    public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
        //获取真正的beanName，主要是解决 工厂Bean 的 & 前缀问题。
        String beanName = transformedBeanName(name);
        //获取父容器的bean。
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            //如果当前容器没有这个bean对象，并且当前容器有父容器，那么就调用父容器的方法获取bean对象.
            return parentBeanFactory.isPrototype(originalBeanName(name));
        }
        //获取一个 RootBeanDefinition 对象。这个对象已经很熟悉了。
        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        if (mbd.isPrototype()) {
            // 如果是工厂bean {FactoryBean} 的话，它的单例还是原型链由自己的控制。
            return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName, mbd));
        }

        // 如果你要判断的是一个工厂bean。
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            return false;
        }
        //如果这是一个 FactoryBean 对象。
        if (isFactoryBean(beanName, mbd)) {
            FactoryBean<?> fb = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
            if (System.getSecurityManager() != null) {
                return AccessController.doPrivileged(
                        (PrivilegedAction<Boolean>) () ->
                                //转换成 SmartFactoryBean 来判断当前bean是不是一个原型链的bean。
                                ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
                                        !fb.isSingleton()),
                        getAccessControlContext());
            }
            else {
                //转换成 SmartFactoryBean 来判断当前bean是不是一个原型链的bean。
                return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) ||
                        !fb.isSingleton());
            }
        }
        else {
            return false;
        }
    }

    /**
     * 检查当前beanName 的bean是否匹配这个类型。
     */
    @Override
    public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
        return isTypeMatch(name, typeToMatch, true);
    }

    /**
     * 检查当前beanName 的bean是否匹配这个类型的具体方法。
     */
    protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit)
            throws NoSuchBeanDefinitionException {
        //获取这个bean真正的名字。
        String beanName = transformedBeanName(name);
        //判断这个名字是不是一个 工厂bean。
        boolean isFactoryDereference = BeanFactoryUtils.isFactoryDereference(name);

        //先从缓存中获取一个 单例bean。
        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
            //如果是一个工厂bean。
            if (beanInstance instanceof FactoryBean) {
                if (!isFactoryDereference) {
                    Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance);
                    return (type != null && typeToMatch.isAssignableFrom(type));
                }
                else {
                    return typeToMatch.isInstance(beanInstance);
                }
            }
            //如果不是一个 工厂bean。
            else if (!isFactoryDereference) {
                if (typeToMatch.isInstance(beanInstance)) {
                    // Direct match for exposed instance?
                    return true;
                }
                else if (typeToMatch.hasGenerics() && containsBeanDefinition(beanName)) {
                    // 获取 rootBeanDefinition 对象。
                    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                    Class<?> targetType = mbd.getTargetType();
                    if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance)) {
                        // Check raw class match as well, making sure it's exposed on the proxy.
                        Class<?> classToMatch = typeToMatch.resolve();
                        if (classToMatch != null && !classToMatch.isInstance(beanInstance)) {
                            return false;
                        }
                        if (typeToMatch.isAssignableFrom(targetType)) {
                            return true;
                        }
                    }
                    ResolvableType resolvableType = mbd.targetType;
                    if (resolvableType == null) {
                        resolvableType = mbd.factoryMethodReturnType;
                    }
                    return (resolvableType != null && typeToMatch.isAssignableFrom(resolvableType));
                }
            }
            return false;
        }
        else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
            // null instance registered
            return false;
        }

        // No singleton instance found -> check bean definition.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // No bean definition found in this factory -> delegate to parent.
            return parentBeanFactory.isTypeMatch(originalBeanName(name), typeToMatch);
        }

        // Retrieve corresponding bean definition.
        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();

        // Setup the types that we want to match against
        Class<?> classToMatch = typeToMatch.resolve();
        if (classToMatch == null) {
            classToMatch = FactoryBean.class;
        }
        Class<?>[] typesToMatch = (FactoryBean.class == classToMatch ?
                new Class<?>[] {classToMatch} : new Class<?>[] {FactoryBean.class, classToMatch});


        // Attempt to predict the bean type
        Class<?> predictedType = null;

        // We're looking for a regular reference but we're a factory bean that has
        // a decorated bean definition. The target bean should be the same type
        // as FactoryBean would ultimately return.
        if (!isFactoryDereference && dbd != null && isFactoryBean(beanName, mbd)) {
            // We should only attempt if the user explicitly set lazy-init to true
            // and we know the merged bean definition is for a factory bean.
            if (!mbd.isLazyInit() || allowFactoryBeanInit) {
                RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
                Class<?> targetType = predictBeanType(dbd.getBeanName(), tbd, typesToMatch);
                if (targetType != null && !FactoryBean.class.isAssignableFrom(targetType)) {
                    predictedType = targetType;
                }
            }
        }

        // If we couldn't use the target type, try regular prediction.
        if (predictedType == null) {
            predictedType = predictBeanType(beanName, mbd, typesToMatch);
            if (predictedType == null) {
                return false;
            }
        }

        // Attempt to get the actual ResolvableType for the bean.
        ResolvableType beanType = null;

        // If it's a FactoryBean, we want to look at what it creates, not the factory class.
        if (FactoryBean.class.isAssignableFrom(predictedType)) {
            if (beanInstance == null && !isFactoryDereference) {
                beanType = getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit);
                predictedType = beanType.resolve();
                if (predictedType == null) {
                    return false;
                }
            }
        }
        else if (isFactoryDereference) {
            // Special case: A SmartInstantiationAwareBeanPostProcessor returned a non-FactoryBean
            // type but we nevertheless are being asked to dereference a FactoryBean...
            // Let's check the original bean class and proceed with it if it is a FactoryBean.
            predictedType = predictBeanType(beanName, mbd, FactoryBean.class);
            if (predictedType == null || !FactoryBean.class.isAssignableFrom(predictedType)) {
                return false;
            }
        }

        // We don't have an exact type but if bean definition target type or the factory
        // method return type matches the predicted type then we can use that.
        if (beanType == null) {
            ResolvableType definedType = mbd.targetType;
            if (definedType == null) {
                definedType = mbd.factoryMethodReturnType;
            }
            if (definedType != null && definedType.resolve() == predictedType) {
                beanType = definedType;
            }
        }

        // If we have a bean type use it so that generics are considered
        if (beanType != null) {
            return typeToMatch.isAssignableFrom(beanType);
        }

        // If we don't have a bean type, fallback to the predicted type
        return typeToMatch.isAssignableFrom(predictedType);
    }

    @Override
    public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
        return isTypeMatch(name, ResolvableType.forRawClass(typeToMatch));
    }

    @Override
    @Nullable
    public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return getType(name, true);
    }

    /**
     * 根据beanName，获取当前bean的class对象，主要需要区分：工厂bean和普通的bean。
     */
    @Override
    @Nullable
    public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
        String beanName = transformedBeanName(name);

        // Check manually registered singletons.
        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
            if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
                return getTypeForFactoryBean((FactoryBean<?>) beanInstance);
            }
            else {
                return beanInstance.getClass();
            }
        }

        // No singleton instance found -> check bean definition.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // No bean definition found in this factory -> delegate to parent.
            return parentBeanFactory.getType(originalBeanName(name));
        }

        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

        // Check decorated bean definition, if any: We assume it'll be easier
        // to determine the decorated bean's type than the proxy's type.
        BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
        if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
            RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
            Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd);
            if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
                return targetClass;
            }
        }

        Class<?> beanClass = predictBeanType(beanName, mbd);

        // Check bean class whether we're dealing with a FactoryBean.
        if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) {
            if (!BeanFactoryUtils.isFactoryDereference(name)) {
                // If it's a FactoryBean, we want to look at what it creates, not at the factory class.
                return getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit).resolve();
            }
            else {
                return beanClass;
            }
        }
        else {
            return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass : null);
        }
    }

    /**
     * 根据beanName 获取一个别名列表。
     */
    @Override
    public String[] getAliases(String name) {
        String beanName = transformedBeanName(name);
        List<String> aliases = new ArrayList<>();
        boolean factoryPrefix = name.startsWith(FACTORY_BEAN_PREFIX);
        String fullBeanName = beanName;
        if (factoryPrefix) {
            fullBeanName = FACTORY_BEAN_PREFIX + beanName;
        }
        if (!fullBeanName.equals(name)) {
            aliases.add(fullBeanName);
        }
        String[] retrievedAliases = super.getAliases(beanName);
        String prefix = factoryPrefix ? FACTORY_BEAN_PREFIX : "";
        for (String retrievedAlias : retrievedAliases) {
            String alias = prefix + retrievedAlias;
            if (!alias.equals(name)) {
                aliases.add(alias);
            }
        }
        if (!containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null) {
                aliases.addAll(Arrays.asList(parentBeanFactory.getAliases(fullBeanName)));
            }
        }
        return StringUtils.toStringArray(aliases);
    }


    //---------------------------------------------------------------------
    //实现 HierarchicalBeanFactory 接口的方法
    //---------------------------------------------------------------------

    @Override
    @Nullable
    public BeanFactory getParentBeanFactory() {
        return this.parentBeanFactory;
    }

    @Override
    public boolean containsLocalBean(String name) {
        String beanName = transformedBeanName(name);
        return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) &&
                (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName)));
    }


    //---------------------------------------------------------------------
    // 实现 ConfigurableBeanFactory 接口的方法
    //---------------------------------------------------------------------

    @Override
    public void setParentBeanFactory(@Nullable BeanFactory parentBeanFactory) {
        if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
            throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
        }
        if (this == parentBeanFactory) {
            throw new IllegalStateException("Cannot set parent bean factory to self");
        }
        this.parentBeanFactory = parentBeanFactory;
    }

    @Override
    public void setBeanClassLoader(@Nullable ClassLoader beanClassLoader) {
        this.beanClassLoader = (beanClassLoader != null ? beanClassLoader : ClassUtils.getDefaultClassLoader());
    }

    @Override
    @Nullable
    public ClassLoader getBeanClassLoader() {
        return this.beanClassLoader;
    }

    @Override
    public void setTempClassLoader(@Nullable ClassLoader tempClassLoader) {
        this.tempClassLoader = tempClassLoader;
    }

    @Override
    @Nullable
    public ClassLoader getTempClassLoader() {
        return this.tempClassLoader;
    }

    @Override
    public void setCacheBeanMetadata(boolean cacheBeanMetadata) {
        this.cacheBeanMetadata = cacheBeanMetadata;
    }

    @Override
    public boolean isCacheBeanMetadata() {
        return this.cacheBeanMetadata;
    }

    @Override
    public void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver) {
        this.beanExpressionResolver = resolver;
    }

    @Override
    @Nullable
    public BeanExpressionResolver getBeanExpressionResolver() {
        return this.beanExpressionResolver;
    }

    @Override
    public void setConversionService(@Nullable ConversionService conversionService) {
        this.conversionService = conversionService;
    }

    @Override
    @Nullable
    public ConversionService getConversionService() {
        return this.conversionService;
    }

    @Override
    public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) {
        Assert.notNull(registrar, "PropertyEditorRegistrar must not be null");
        this.propertyEditorRegistrars.add(registrar);
    }

    /**
     * Return the set of PropertyEditorRegistrars.
     */
    public Set<PropertyEditorRegistrar> getPropertyEditorRegistrars() {
        return this.propertyEditorRegistrars;
    }

    @Override
    public void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass) {
        Assert.notNull(requiredType, "Required type must not be null");
        Assert.notNull(propertyEditorClass, "PropertyEditor class must not be null");
        this.customEditors.put(requiredType, propertyEditorClass);
    }

    @Override
    public void copyRegisteredEditorsTo(PropertyEditorRegistry registry) {
        registerCustomEditors(registry);
    }

    /**
     * Return the map of custom editors, with Classes as keys and PropertyEditor classes as values.
     */
    public Map<Class<?>, Class<? extends PropertyEditor>> getCustomEditors() {
        return this.customEditors;
    }

    @Override
    public void setTypeConverter(TypeConverter typeConverter) {
        this.typeConverter = typeConverter;
    }

    /**
     * Return the custom TypeConverter to use, if any.
     * @return the custom TypeConverter, or {@code null} if none specified
     */
    @Nullable
    protected TypeConverter getCustomTypeConverter() {
        return this.typeConverter;
    }

    @Override
    public TypeConverter getTypeConverter() {
        TypeConverter customConverter = getCustomTypeConverter();
        if (customConverter != null) {
            return customConverter;
        }
        else {
            // Build default TypeConverter, registering custom editors.
            SimpleTypeConverter typeConverter = new SimpleTypeConverter();
            typeConverter.setConversionService(getConversionService());
            registerCustomEditors(typeConverter);
            return typeConverter;
        }
    }

    @Override
    public void addEmbeddedValueResolver(StringValueResolver valueResolver) {
        Assert.notNull(valueResolver, "StringValueResolver must not be null");
        this.embeddedValueResolvers.add(valueResolver);
    }

    @Override
    public boolean hasEmbeddedValueResolver() {
        return !this.embeddedValueResolvers.isEmpty();
    }

    @Override
    @Nullable
    public String resolveEmbeddedValue(@Nullable String value) {
        if (value == null) {
            return null;
        }
        String result = value;
        for (StringValueResolver resolver : this.embeddedValueResolvers) {
            result = resolver.resolveStringValue(result);
            if (result == null) {
                return null;
            }
        }
        return result;
    }

    /**
     * 添加 BeanPostProcessor 实现类。
     */
    @Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
        // 如果存在旧的 BeanPostProcessor 那就先删除旧的。
        this.beanPostProcessors.remove(beanPostProcessor);
        // 一个标记。这两类的 BeanPostProcessor 在容器的初始化过程中有不同的处理逻辑。
        if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
            this.hasInstantiationAwareBeanPostProcessors = true;
        }
        if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
            this.hasDestructionAwareBeanPostProcessors = true;
        }
        // 在队列尾部添加一个 BeanPostProcessor 。
        this.beanPostProcessors.add(beanPostProcessor);
    }

    @Override
    public int getBeanPostProcessorCount() {
        return this.beanPostProcessors.size();
    }

    /**
     * 返回 BeanPostProcessor 集合。
     */
    public List<BeanPostProcessor> getBeanPostProcessors() {
        return this.beanPostProcessors;
    }

    /**
     * 判断当前容器中是否有 InstantiationAwareBeanPostProcessor 的实现类。
     */
    protected boolean hasInstantiationAwareBeanPostProcessors() {
        return this.hasInstantiationAwareBeanPostProcessors;
    }

    /**
     * 判断当前容器中是否有 DestructionAwareBeanPostProcessor 在单例bean的销毁过程中会调用这个方法。
     */
    protected boolean hasDestructionAwareBeanPostProcessors() {
        return this.hasDestructionAwareBeanPostProcessors;
    }

    /**
     * 向容器中注册一个 Scope，注意这个不能注册 singleton 和 prototype 的作用域，
     *      这个方法的使用地方在：我知道的地方就是在 web 容器中需要额外定义一些 request、session 的作用域。
     */
    @Override
    public void registerScope(String scopeName, Scope scope) {
        Assert.notNull(scopeName, "Scope identifier must not be null");
        Assert.notNull(scope, "Scope must not be null");
        if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) {
            throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'");
        }
        Scope previous = this.scopes.put(scopeName, scope);
        if (previous != null && previous != scope) {
            if (logger.isDebugEnabled()) {
                logger.debug("Replacing scope '" + scopeName + "' from [" + previous + "] to [" + scope + "]");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Registering scope '" + scopeName + "' with implementation [" + scope + "]");
            }
        }
    }

    @Override
    public String[] getRegisteredScopeNames() {
        return StringUtils.toStringArray(this.scopes.keySet());
    }

    @Override
    @Nullable
    public Scope getRegisteredScope(String scopeName) {
        Assert.notNull(scopeName, "Scope identifier must not be null");
        return this.scopes.get(scopeName);
    }

    public void setSecurityContextProvider(SecurityContextProvider securityProvider) {
        this.securityContextProvider = securityProvider;
    }

    @Override
    public AccessControlContext getAccessControlContext() {
        return (this.securityContextProvider != null ?
                this.securityContextProvider.getAccessControlContext() :
                AccessController.getContext());
    }

    /**
     * 复制容器的方法。
     */
    @Override
    public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
        Assert.notNull(otherFactory, "BeanFactory must not be null");
        setBeanClassLoader(otherFactory.getBeanClassLoader());
        setCacheBeanMetadata(otherFactory.isCacheBeanMetadata());
        setBeanExpressionResolver(otherFactory.getBeanExpressionResolver());
        setConversionService(otherFactory.getConversionService());
        if (otherFactory instanceof org.springframework.beans.factory.support.AbstractBeanFactory) {
            org.springframework.beans.factory.support.AbstractBeanFactory otherAbstractFactory = (org.springframework.beans.factory.support.AbstractBeanFactory) otherFactory;
            this.propertyEditorRegistrars.addAll(otherAbstractFactory.propertyEditorRegistrars);
            this.customEditors.putAll(otherAbstractFactory.customEditors);
            this.typeConverter = otherAbstractFactory.typeConverter;
            this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
            this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
                    otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
            this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors ||
                    otherAbstractFactory.hasDestructionAwareBeanPostProcessors;
            this.scopes.putAll(otherAbstractFactory.scopes);
            this.securityContextProvider = otherAbstractFactory.securityContextProvider;
        }
        else {
            setTypeConverter(otherFactory.getTypeConverter());
            String[] otherScopeNames = otherFactory.getRegisteredScopeNames();
            for (String scopeName : otherScopeNames) {
                this.scopes.put(scopeName, otherFactory.getRegisteredScope(scopeName));
            }
        }
    }

    /**
     * 返回一个 merged BeanDefinition 的对象。主要和 合并 子BeanDefinition 和 父BeanDefinition 对象。
     * 返回的结果为 RootBeanDefinition。
     */
    @Override
    public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
        String beanName = transformedBeanName(name);
        // Efficiently check whether bean definition exists in this factory.
        if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
            return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
        }
        // Resolve merged bean definition locally.
        return getMergedLocalBeanDefinition(beanName);
    }

    /**
     * 根据 beanName 来判断当前bean是不是一个 工厂bean。
     */
    @Override
    public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
        String beanName = transformedBeanName(name);
        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null) {
            return (beanInstance instanceof FactoryBean);
        }
        // No singleton instance found -> check bean definition.
        if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
            // No bean definition found in this factory -> delegate to parent.
            return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
        }
        return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
    }

    /**
     * 根据 beanName 来判断容器当前是不是正在创建这个bean。
     */
    @Override
    public boolean isActuallyInCreation(String beanName) {
        return (isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName));
    }

    /**
     * 判断当前bean是一个原型链的bean，并且正在创建（在当前线程中）。
     */
    protected boolean isPrototypeCurrentlyInCreation(String beanName) {
        Object curVal = this.prototypesCurrentlyInCreation.get();
        return (curVal != null &&
                (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
    }

    /**
     * 创建一个 原型链的 bean，的前置操作，比如先 标记下 当前bean正在被创建。
     */
    @SuppressWarnings("unchecked")
    protected void beforePrototypeCreation(String beanName) {
        Object curVal = this.prototypesCurrentlyInCreation.get();
        if (curVal == null) {
            this.prototypesCurrentlyInCreation.set(beanName);
        }
        else if (curVal instanceof String) {
            Set<String> beanNameSet = new HashSet<>(2);
            beanNameSet.add((String) curVal);
            beanNameSet.add(beanName);
            this.prototypesCurrentlyInCreation.set(beanNameSet);
        }
        else {
            Set<String> beanNameSet = (Set<String>) curVal;
            beanNameSet.add(beanName);
        }
    }

    /**
     * 创建原型链bean之后调用的方法，主要就是 清除之前的标记，表示当前bean已经被创建好了。
     *      这个标记我知道会在判断 原型链bean 是否出现循环依赖的情况。
     */
    @SuppressWarnings("unchecked")
    protected void afterPrototypeCreation(String beanName) {
        Object curVal = this.prototypesCurrentlyInCreation.get();
        if (curVal instanceof String) {
            this.prototypesCurrentlyInCreation.remove();
        }
        else if (curVal instanceof Set) {
            Set<String> beanNameSet = (Set<String>) curVal;
            beanNameSet.remove(beanName);
            if (beanNameSet.isEmpty()) {
                this.prototypesCurrentlyInCreation.remove();
            }
        }
    }

    @Override
    public void destroyBean(String beanName, Object beanInstance) {
        destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName));
    }

    /**
     * 销毁bean的方法，主要就是调用 destory-method。
     */
    protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
    }

    @Override
    public void destroyScopedBean(String beanName) {
        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        if (mbd.isSingleton() || mbd.isPrototype()) {
            throw new IllegalArgumentException(
                    "Bean name '" + beanName + "' does not correspond to an object in a mutable scope");
        }
        String scopeName = mbd.getScope();
        Scope scope = this.scopes.get(scopeName);
        if (scope == null) {
            throw new IllegalStateException("No Scope SPI registered for scope name '" + scopeName + "'");
        }
        Object bean = scope.remove(beanName);
        if (bean != null) {
            destroyBean(beanName, bean, mbd);
        }
    }


    //---------------------------------------------------------------------
    //自己类中实现的方法。
    //---------------------------------------------------------------------

    /**
     * 返回bean的名字，主要是解决 {FactoryBean} 的命名问题。
     * 比如 FactoryBean名字为 {@code &UserName} 就会返回 {@code UserName}。
     */
    protected String transformedBeanName(String name) {
        return canonicalName(BeanFactoryUtils.transformedBeanName(name));
    }

    /**
     * Determine the original bean name, resolving locally defined aliases to canonical names.
     * @param name the user-specified name
     * @return the original bean name
     */
    protected String originalBeanName(String name) {
        String beanName = transformedBeanName(name);
        if (name.startsWith(FACTORY_BEAN_PREFIX)) {
            beanName = FACTORY_BEAN_PREFIX + beanName;
        }
        return beanName;
    }

    /**
     * 初始化一个 BeanWarrper 对象。
     */
    protected void initBeanWrapper(BeanWrapper bw) {
        bw.setConversionService(getConversionService());
        registerCustomEditors(bw);
    }

    protected void registerCustomEditors(PropertyEditorRegistry registry) {
        PropertyEditorRegistrySupport registrySupport =
                (registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
        if (registrySupport != null) {
            registrySupport.useConfigValueEditors();
        }
        if (!this.propertyEditorRegistrars.isEmpty()) {
            for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
                try {
                    registrar.registerCustomEditors(registry);
                }
                catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        String bceBeanName = bce.getBeanName();
                        if (bceBeanName != null && isCurrentlyInCreation(bceBeanName)) {
                            if (logger.isDebugEnabled()) {
                                logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
                                        "] failed because it tried to obtain currently created bean '" +
                                        ex.getBeanName() + "': " + ex.getMessage());
                            }
                            onSuppressedException(ex);
                            continue;
                        }
                    }
                    throw ex;
                }
            }
        }
        if (!this.customEditors.isEmpty()) {
            this.customEditors.forEach((requiredType, editorClass) ->
                    registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)));
        }
    }


    /**
     * 返回一个 合并的 RootBeanDefinition 对象。之前说了，这个方法是为了消除父子关系的 BeanDefinition 的关系。
     */
    protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
        //先从缓存中获取，如果没有在执行merge操作。
        RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
        if (mbd != null && !mbd.stale) {
            return mbd;
        }
        return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
    }

    protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
            throws BeanDefinitionStoreException {

        return getMergedBeanDefinition(beanName, bd, null);
    }

    /**
     * 根据父子关系返回一个 RootBeanDefinition 对象
     * 关系如下：
     *      如果当前对象没有父关系： 则直接返回子对象。
     *      如果存在父关系：
     *          则拿到父关系：和子对象进行合并，如果有多层调用，则需要递归处理。
     *     总之合并的目的就是让最终的 RootBeanDefinition 同时拥有 父子定义的全部结构。
     *
     */
    protected RootBeanDefinition getMergedBeanDefinition(
            String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
            throws BeanDefinitionStoreException {

        synchronized (this.mergedBeanDefinitions) {
            RootBeanDefinition mbd = null;
            RootBeanDefinition previous = null;

            // Check with full lock now in order to enforce the same merged instance.
            if (containingBd == null) {
                mbd = this.mergedBeanDefinitions.get(beanName);
            }

            if (mbd == null || mbd.stale) {
                previous = mbd;
                if (bd.getParentName() == null) {
                    // Use copy of given root bean definition.
                    if (bd instanceof RootBeanDefinition) {
                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                    }
                    else {
                        mbd = new RootBeanDefinition(bd);
                    }
                }
                else {
                    // Child bean definition: needs to be merged with parent.
                    BeanDefinition pbd;
                    try {
                        String parentBeanName = transformedBeanName(bd.getParentName());
                        if (!beanName.equals(parentBeanName)) {
                            pbd = getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            BeanFactory parent = getParentBeanFactory();
                            if (parent instanceof ConfigurableBeanFactory) {
                                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                            }
                            else {
                                throw new NoSuchBeanDefinitionException(parentBeanName,
                                        "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                                "': cannot be resolved without a ConfigurableBeanFactory parent");
                            }
                        }
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                    }
                    // Deep copy with overridden values.
                    mbd = new RootBeanDefinition(pbd);
                    mbd.overrideFrom(bd);
                }

                // Set default singleton scope, if not configured before.
                if (!StringUtils.hasLength(mbd.getScope())) {
                    mbd.setScope(SCOPE_SINGLETON);
                }

                // A bean contained in a non-singleton bean cannot be a singleton itself.
                // Let's correct this on the fly here, since this might be the result of
                // parent-child merging for the outer bean, in which case the original inner bean
                // definition will not have inherited the merged outer bean's singleton status.
                if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                    mbd.setScope(containingBd.getScope());
                }

                // Cache the merged bean definition for the time being
                // (it might still get re-merged later on in order to pick up metadata changes)
                if (containingBd == null && isCacheBeanMetadata()) {
                    this.mergedBeanDefinitions.put(beanName, mbd);
                }
            }
            if (previous != null) {
                copyRelevantMergedBeanDefinitionCaches(previous, mbd);
            }
            return mbd;
        }
    }

    /**
     * 合并的方法。
     */
    private void copyRelevantMergedBeanDefinitionCaches(RootBeanDefinition previous, RootBeanDefinition mbd) {
        if (ObjectUtils.nullSafeEquals(mbd.getBeanClassName(), previous.getBeanClassName()) &&
                ObjectUtils.nullSafeEquals(mbd.getFactoryBeanName(), previous.getFactoryBeanName()) &&
                ObjectUtils.nullSafeEquals(mbd.getFactoryMethodName(), previous.getFactoryMethodName())) {
            ResolvableType targetType = mbd.targetType;
            ResolvableType previousTargetType = previous.targetType;
            if (targetType == null || targetType.equals(previousTargetType)) {
                mbd.targetType = previousTargetType;
                mbd.isFactoryBean = previous.isFactoryBean;
                mbd.resolvedTargetType = previous.resolvedTargetType;
                mbd.factoryMethodReturnType = previous.factoryMethodReturnType;
                mbd.factoryMethodToIntrospect = previous.factoryMethodToIntrospect;
            }
        }
    }

    /**
     * 判断一下合成之后的 BeanDefinition 是不是一个抽象类。
     */
    protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
            throws BeanDefinitionStoreException {

        if (mbd.isAbstract()) {
            throw new BeanIsAbstractException(beanName);
        }
    }

    /**
     * 移除一个 BeanDefinition 对象。
     */
    protected void clearMergedBeanDefinition(String beanName) {
        RootBeanDefinition bd = this.mergedBeanDefinitions.get(beanName);
        if (bd != null) {
            bd.stale = true;
        }
    }

    public void clearMetadataCache() {
        this.mergedBeanDefinitions.forEach((beanName, bd) -> {
            if (!isBeanEligibleForMetadataCaching(beanName)) {
                bd.stale = true;
            }
        });
    }

    /**
     * 根据beanName去返回 class 对象。
     */
    @Nullable
    protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
            throws CannotLoadBeanClassException {
        try {
            if (mbd.hasBeanClass()) {
                return mbd.getBeanClass();
            }
            if (System.getSecurityManager() != null) {
                return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
                        () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
            }
            else {
                return doResolveBeanClass(mbd, typesToMatch);
            }
        }
        catch (PrivilegedActionException pae) {
            ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
            throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
        }
        catch (ClassNotFoundException ex) {
            throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
        }
        catch (LinkageError err) {
            throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
        }
    }

    @Nullable
    private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
            throws ClassNotFoundException {

        ClassLoader beanClassLoader = getBeanClassLoader();
        ClassLoader dynamicLoader = beanClassLoader;
        boolean freshResolve = false;

        if (!ObjectUtils.isEmpty(typesToMatch)) {
            // When just doing type checks (i.e. not creating an actual instance yet),
            // use the specified temporary class loader (e.g. in a weaving scenario).
            ClassLoader tempClassLoader = getTempClassLoader();
            if (tempClassLoader != null) {
                dynamicLoader = tempClassLoader;
                freshResolve = true;
                if (tempClassLoader instanceof DecoratingClassLoader) {
                    DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
                    for (Class<?> typeToMatch : typesToMatch) {
                        dcl.excludeClass(typeToMatch.getName());
                    }
                }
            }
        }

        String className = mbd.getBeanClassName();
        if (className != null) {
            Object evaluated = evaluateBeanDefinitionString(className, mbd);
            if (!className.equals(evaluated)) {
                // A dynamically resolved expression, supported as of 4.2...
                if (evaluated instanceof Class) {
                    return (Class<?>) evaluated;
                }
                else if (evaluated instanceof String) {
                    className = (String) evaluated;
                    freshResolve = true;
                }
                else {
                    throw new IllegalStateException("Invalid class name expression result: " + evaluated);
                }
            }
            if (freshResolve) {
                // When resolving against a temporary class loader, exit early in order
                // to avoid storing the resolved Class in the bean definition.
                if (dynamicLoader != null) {
                    try {
                        return dynamicLoader.loadClass(className);
                    }
                    catch (ClassNotFoundException ex) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
                        }
                    }
                }
                return ClassUtils.forName(className, dynamicLoader);
            }
        }

        // Resolve regularly, caching the result in the BeanDefinition...
        return mbd.resolveBeanClass(beanClassLoader);
    }

    /**
     * Evaluate the given String as contained in a bean definition,
     * potentially resolving it as an expression.
     * @param value the value to check
     * @param beanDefinition the bean definition that the value comes from
     * @return the resolved value
     * @see #setBeanExpressionResolver
     */
    @Nullable
    protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) {
        if (this.beanExpressionResolver == null) {
            return value;
        }

        Scope scope = null;
        if (beanDefinition != null) {
            String scopeName = beanDefinition.getScope();
            if (scopeName != null) {
                scope = getRegisteredScope(scopeName);
            }
        }
        return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
    }


    /**
     * Predict the eventual bean type (of the processed bean instance) for the
     * specified bean. Called by {@link #getType} and {@link #isTypeMatch}.
     * Does not need to handle FactoryBeans specifically, since it is only
     * supposed to operate on the raw bean type.
     * <p>This implementation is simplistic in that it is not able to
     * handle factory methods and InstantiationAwareBeanPostProcessors.
     * It only predicts the bean type correctly for a standard bean.
     * To be overridden in subclasses, applying more sophisticated type detection.
     * @param beanName the name of the bean
     * @param mbd the merged bean definition to determine the type for
     * @param typesToMatch the types to match in case of internal type matching purposes
     * (also signals that the returned {@code Class} will never be exposed to application code)
     * @return the type of the bean, or {@code null} if not predictable
     */
    @Nullable
    protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
        Class<?> targetType = mbd.getTargetType();
        if (targetType != null) {
            return targetType;
        }
        if (mbd.getFactoryMethodName() != null) {
            return null;
        }
        return resolveBeanClass(mbd, beanName, typesToMatch);
    }

    /**
     * Check whether the given bean is defined as a {@link FactoryBean}.
     * @param beanName the name of the bean
     * @param mbd the corresponding bean definition
     */
    protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
        Boolean result = mbd.isFactoryBean;
        if (result == null) {
            Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
            result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
            mbd.isFactoryBean = result;
        }
        return result;
    }

    /**
     * Determine the bean type for the given FactoryBean definition, as far as possible.
     * Only called if there is no singleton instance registered for the target bean
     * already. The implementation is allowed to instantiate the target factory bean if
     * {@code allowInit} is {@code true} and the type cannot be determined another way;
     * otherwise it is restricted to introspecting signatures and related metadata.
     * <p>If no {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} if set on the bean definition
     * and {@code allowInit} is {@code true}, the default implementation will create
     * the FactoryBean via {@code getBean} to call its {@code getObjectType} method.
     * Subclasses are encouraged to optimize this, typically by inspecting the generic
     * signature of the factory bean class or the factory method that creates it.
     * If subclasses do instantiate the FactoryBean, they should consider trying the
     * {@code getObjectType} method without fully populating the bean. If this fails,
     * a full FactoryBean creation as performed by this implementation should be used
     * as fallback.
     * @param beanName the name of the bean
     * @param mbd the merged bean definition for the bean
     * @param allowInit if initialization of the FactoryBean is permitted if the type
     * cannot be determined another way
     * @return the type for the bean if determinable, otherwise {@code ResolvableType.NONE}
     * @since 5.2
     * @see org.springframework.beans.factory.FactoryBean#getObjectType()
     * @see #getBean(String)
     */
    protected ResolvableType getTypeForFactoryBean(String beanName, RootBeanDefinition mbd, boolean allowInit) {
        ResolvableType result = getTypeForFactoryBeanFromAttributes(mbd);
        if (result != ResolvableType.NONE) {
            return result;
        }

        if (allowInit && mbd.isSingleton()) {
            try {
                FactoryBean<?> factoryBean = doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true);
                Class<?> objectType = getTypeForFactoryBean(factoryBean);
                return (objectType != null ? ResolvableType.forClass(objectType) : ResolvableType.NONE);
            }
            catch (BeanCreationException ex) {
                if (ex.contains(BeanCurrentlyInCreationException.class)) {
                    logger.trace(LogMessage.format("Bean currently in creation on FactoryBean type check: %s", ex));
                }
                else if (mbd.isLazyInit()) {
                    logger.trace(LogMessage.format("Bean creation exception on lazy FactoryBean type check: %s", ex));
                }
                else {
                    logger.debug(LogMessage.format("Bean creation exception on eager FactoryBean type check: %s", ex));
                }
                onSuppressedException(ex);
            }
        }
        return ResolvableType.NONE;
    }

    /**
     * Determine the bean type for a FactoryBean by inspecting its attributes for a
     * {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} value.
     * @param attributes the attributes to inspect
     * @return a {@link ResolvableType} extracted from the attributes or
     * {@code ResolvableType.NONE}
     * @since 5.2
     */
    ResolvableType getTypeForFactoryBeanFromAttributes(AttributeAccessor attributes) {
        Object attribute = attributes.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE);
        if (attribute instanceof ResolvableType) {
            return (ResolvableType) attribute;
        }
        if (attribute instanceof Class) {
            return ResolvableType.forClass((Class<?>) attribute);
        }
        return ResolvableType.NONE;
    }

    /**
     * Determine the bean type for the given FactoryBean definition, as far as possible.
     * Only called if there is no singleton instance registered for the target bean already.
     * <p>The default implementation creates the FactoryBean via {@code getBean}
     * to call its {@code getObjectType} method. Subclasses are encouraged to optimize
     * this, typically by just instantiating the FactoryBean but not populating it yet,
     * trying whether its {@code getObjectType} method already returns a type.
     * If no type found, a full FactoryBean creation as performed by this implementation
     * should be used as fallback.
     * @param beanName the name of the bean
     * @param mbd the merged bean definition for the bean
     * @return the type for the bean if determinable, or {@code null} otherwise
     * @see org.springframework.beans.factory.FactoryBean#getObjectType()
     * @see #getBean(String)
     * @deprecated since 5.2 in favor of {@link #getTypeForFactoryBean(String, RootBeanDefinition, boolean)}
     */
    @Nullable
    @Deprecated
    protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
        return getTypeForFactoryBean(beanName, mbd, true).resolve();
    }

    /**
     * Mark the specified bean as already created (or about to be created).
     * <p>This allows the bean factory to optimize its caching for repeated
     * creation of the specified bean.
     * @param beanName the name of the bean
     */
    protected void markBeanAsCreated(String beanName) {
        if (!this.alreadyCreated.contains(beanName)) {
            synchronized (this.mergedBeanDefinitions) {
                if (!this.alreadyCreated.contains(beanName)) {
                    // Let the bean definition get re-merged now that we're actually creating
                    // the bean... just in case some of its metadata changed in the meantime.
                    clearMergedBeanDefinition(beanName);
                    this.alreadyCreated.add(beanName);
                }
            }
        }
    }

    /**
     * Perform appropriate cleanup of cached metadata after bean creation failed.
     * @param beanName the name of the bean
     */
    protected void cleanupAfterBeanCreationFailure(String beanName) {
        synchronized (this.mergedBeanDefinitions) {
            this.alreadyCreated.remove(beanName);
        }
    }

    /**
     * Determine whether the specified bean is eligible for having
     * its bean definition metadata cached.
     * @param beanName the name of the bean
     * @return {@code true} if the bean's metadata may be cached
     * at this point already
     */
    protected boolean isBeanEligibleForMetadataCaching(String beanName) {
        return this.alreadyCreated.contains(beanName);
    }

    /**
     * Remove the singleton instance (if any) for the given bean name,
     * but only if it hasn't been used for other purposes than type checking.
     * @param beanName the name of the bean
     * @return {@code true} if actually removed, {@code false} otherwise
     */
    protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
        if (!this.alreadyCreated.contains(beanName)) {
            removeSingleton(beanName);
            return true;
        }
        else {
            return false;
        }
    }

    /**
     * Check whether this factory's bean creation phase already started,
     * i.e. whether any bean has been marked as created in the meantime.
     * @since 4.2.2
     * @see #markBeanAsCreated
     */
    protected boolean hasBeanCreationStarted() {
        return !this.alreadyCreated.isEmpty();
    }

    /**
     * 返回真正的bean对象，无论这个bean是正常的bean，还是 FactoryBean ，都会返回真正的bean。
     * 也就是说 如果当前bean为工厂bean 那么就会调用 {@link FactoryBean#getObject()} 方法获取bean。
     */
    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

        // Don't let calling code try to dereference the factory if the bean isn't a factory.
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
            if (mbd != null) {
                mbd.isFactoryBean = true;
            }
            return beanInstance;
        }

        // Now we have the bean instance, which may be a normal bean or a FactoryBean.
        // If it's a FactoryBean, we use it to create a bean instance, unless the
        // caller actually wants a reference to the factory.
        if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }

        Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        else {
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {
            // Return bean instance from factory.
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // Caches object obtained from FactoryBean if it is a singleton.
            if (mbd == null && containsBeanDefinition(beanName)) {
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }

    /**
     * Determine whether the given bean name is already in use within this factory,
     * i.e. whether there is a local bean or alias registered under this name or
     * an inner bean created with this name.
     * @param beanName the name to check
     */
    public boolean isBeanNameInUse(String beanName) {
        return isAlias(beanName) || containsLocalBean(beanName) || hasDependentBean(beanName);
    }

    /**
     * Determine whether the given bean requires destruction on shutdown.
     * <p>The default implementation checks the DisposableBean interface as well as
     * a specified destroy method and registered DestructionAwareBeanPostProcessors.
     * @param bean the bean instance to check
     * @param mbd the corresponding bean definition
     * @see org.springframework.beans.factory.DisposableBean
     * @see AbstractBeanDefinition#getDestroyMethodName()
     * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
     */
    protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
        return (bean.getClass() != NullBean.class &&
                (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
                        DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
    }

    /**
     * 如果当前的bean实现了销毁的方法，就需要给这个bean注册一个销毁的方法。
     */
    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
        AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
        if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
            if (mbd.isSingleton()) {
                // Register a DisposableBean implementation that performs all destruction
                // work for the given bean: DestructionAwareBeanPostProcessors,
                // DisposableBean interface, custom destroy method.
                registerDisposableBean(beanName,
                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
            }
            else {
                // A bean with a custom scope...
                Scope scope = this.scopes.get(mbd.getScope());
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
                }
                scope.registerDestructionCallback(beanName,
                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
            }
        }
    }


    //---------------------------------------------------------------------
    // 留给子类实现的抽象的方法。
    //---------------------------------------------------------------------

    /**
     * 判断当前容器是否有这个bean。
     */
    protected abstract boolean containsBeanDefinition(String beanName);

    /**
     * 根据beanName获取一个 BeanDefinition 对象。
     */
    protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;

    /**
     * 根据 RootBeanDefinition 生成一个bean的核心方法。由子类实现。
     */
    protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException;

}
